package com.hqbzl.c1.check;

import lombok.Getter;

import javax.xml.crypto.dsig.keyinfo.KeyValue;
import java.io.IOException;
import java.lang.reflect.Array;
import java.nio.file.FileVisitOption;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class TestCheck {

    static class ScanFilter extends Thread {
        protected String filePath;

        @Getter
        final HashMap<String, AtomicInteger> map = new HashMap<>();
        @Getter
        final HashMap<String, ArrayList<String>> kvalus = new HashMap<>();
        @Getter
        final List<String> files = new ArrayList<>();
        @Getter
        final HashSet<String> repeat = new HashSet<>();
        protected final CountDownLatch countDownLatch;
        protected final List<Predicate<Path>> pathPredicate;
        @Getter
        protected AtomicInteger fileCount = new AtomicInteger(0);

        public ScanFilter(String filePath, List<Predicate<Path>> pathPredicate, CountDownLatch countDownLatch) {
            this.filePath = filePath;
            this.pathPredicate = pathPredicate;

            this.countDownLatch = countDownLatch;
        }

        @Override
        public void run() {
            try (final Stream<Path> walk = Files.walk(Paths.get(filePath),4)) {
                Stream<Path> pathStream = walk.filter(Files::isRegularFile).filter(x -> x.toFile().isFile());
                for (Predicate<Path> predicate : pathPredicate) {
                    pathStream = pathStream.filter(predicate);
                }
                pathStream.forEach(x -> {
                    fileCount.incrementAndGet();
                    final String fileName = x.getFileName().toString();
                    files.add(fileName);
                    final String[] split = fileName.trim().split(" ");
                    if (split.length > 1) {
                        final String key = split[0].toUpperCase();
                        kvalus.computeIfAbsent(key, k -> new ArrayList<>()).add(x.toString());
                        final int andIncrement = map.computeIfAbsent(key, k -> new AtomicInteger(0)).incrementAndGet();
                        if (andIncrement > 1) {
                            repeat.add(key);
//                                    System.out.println(andIncrement + " " + x);
//                                    for (String s : kvalus.get(key)) {
//                                        System.out.println("\t" + s);
//                                    }
                        }
                    }
                });
            } catch (Exception e) {

            } finally {
                countDownLatch.countDown();
            }
        }
    }

    public static Map<String, ArrayList<String>> startAfterMerge(final List<String> directionary, final List<Predicate<Path>> filter) {
        Map<String, ArrayList<String>> allHahMap = new HashMap<>();
        final int size = directionary.size();
        final CountDownLatch countDownLatch = new CountDownLatch(size);
        // 保存最终结果
        final ArrayList<ScanFilter> scanFilters = new ArrayList<>();
        directionary.stream().map(x -> {
            final ScanFilter scanFilter = new ScanFilter(x, filter, countDownLatch);
            scanFilters.add(scanFilter);
            return scanFilter;
        }).forEach(x -> x.start());
        //待所有的线程完成目标
        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        AtomicInteger total = new AtomicInteger(0);
        for (ScanFilter scanFilter : scanFilters) {
            final HashMap<String, ArrayList<String>> kvalus = scanFilter.getKvalus();
            kvalus.forEach((k, v) -> {
                allHahMap.computeIfAbsent(k, key -> new ArrayList<>()).addAll(v);
            });
            total.updateAndGet(x -> x + scanFilter.getFileCount().intValue());
        }
        System.out.println("total = " + total);
        return allHahMap;
    }

    public static void main(String[] args) {
        final List<String> list = Arrays.asList("D:\\a1", "D:\\a2", "D:\\a3",
                "e:\\20180727", "e:\\20181014", "e:\\20190731", "e:\\20190922", "e:\\20190924", "e:\\20191222", "e:\\20200101", "e:\\20200912", "e:\\20210704", "e:\\20210705", "e:\\20210726", "e:\\20211203", "e:\\20211204", "e:\\20211205", "e:\\20211210", "e:\\20220130", "e:\\20220216", "e:\\20220220", "e:\\20220221", "e:\\20220222", "e:\\20220223", "e:\\20220505", "e:\\20220705", "e:\\20220805", "e:\\20220811", "e:\\20220812", "e:\\20220813", "e:\\20220814", "e:\\20220815", "e:\\20220816", "e:\\20221125", "e:\\20230305", "e:\\20230312", "e:\\20230325", "e:\\20230329", "e:\\20230330", "e:\\20230504", "e:\\20230520", "e:\\20230520_batch", "e:\\20230526_batch", "e:\\20230709", "e:\\20230723", "e:\\20230813", "e:\\20230814", "e:\\20230815",
                "f:\\20170725", "f:\\20170805", "f:\\20170819", "f:\\20171112", "f:\\20180127", "f:\\20180203", "f:\\20180602", "f:\\20201102", "f:\\20201104", "f:\\20201108", "f:\\20201114", "f:\\20210630", "f:\\20210703", "f:\\20210814", "f:\\20210904", "f:\\20220203", "f:\\20221110", "f:\\20230312", "f:\\20230806", "f:\\20231001", "f:\\20231002", "f:\\20231003", "f:\\20231004", "f:\\20231016", "f:\\20231017", "f:\\223101401",
                "g:\\20210703", "g:\\202230703", "h:\\media"
                //, "I:\\setup\\m3u8\\hitomi_downloader_GUI\\hitomi_downloaded_torrent", "H:\\video\\20231030_1400_2400"
        );
        final Predicate<Path> filter = x -> x.getFileName().toString().endsWith(".mp4");
        final Predicate<Path> filter1 = x -> x.getFileName().toString().indexOf("藤森里穂") != -1;
        final Predicate<Path> filter2 = x -> x.getFileName().toString().indexOf("介绍") != -1;
//        final Predicate<Path> filter = x -> true;
        final List<Predicate<Path>> filters = Arrays.asList(filter, filter1, filter2);
        final Map<String, ArrayList<String>> resultMap = startAfterMerge(list, filters);
        resultMap.forEach((k, v) -> {
            System.out.println(k + "\t" + v.size());
            v.stream().forEach(x -> System.out.println("\t" + x));
            if (v.size() > 1) {
            }
        });
    }

    public static void main3(String[] args) {
        final Map<String, List<String>> kvalus = new HashMap<>();
        final ArrayList<String> list1 = new ArrayList<>();
        list1.add("1");
        list1.add("2");
        final ArrayList<String> list2 = new ArrayList<>();
        list2.add("3");
        list2.add("4");
        kvalus.put("a", list1);
        kvalus.computeIfAbsent("a", k -> new ArrayList<>()).addAll(list2);
        kvalus.forEach((k, v) -> {
            System.out.println("k = " + k);
            System.out.println(v.stream().collect(Collectors.joining(",")));
        });

    }

    public static void main2(String[] args) {
        final Predicate<Path> filter = x -> x.getFileName().toString().endsWith(".mp4");
        // filter();
        final CountDownLatch countDownLatch = new CountDownLatch(1);
        final List<Predicate<Path>> filters = Arrays.asList(filter);
        final ScanFilter scanFilter = new ScanFilter("H:\\video", filters, countDownLatch);
        scanFilter.start();

        try {
            countDownLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("the end");

        final HashMap<String, ArrayList<String>> kvalus = scanFilter.getKvalus();
        final HashMap<String, AtomicInteger> map = scanFilter.getMap();
        System.out.println("map.size() = " + map.size());
//        System.out.println("kvalus = " + kvalus);
        final HashSet<String> repeat = scanFilter.getRepeat();
        for (String r : repeat) {
            System.out.println(r);
            final ArrayList<String> files = kvalus.get(r);
            if (files != null) {
                for (String x : files) {
                    System.out.println("\t" + x);
                }
            }
        }
//        new Thread(new ScanFilter("H:\\media", countDownLatch)).start();


    }


    final static HashMap<String, AtomicInteger> map = new HashMap<>();
    final static HashMap<String, ArrayList<String>> kvalus = new HashMap<>();

    public static void filter() {
        try (final Stream<Path> walk = Files.walk(Paths.get("H:\\media"))) {
            walk.filter(Files::isRegularFile)
                    .filter(x -> x.toFile().isFile())
                    .filter(x -> x.getFileName().toString().endsWith(".mp4"))
                    .forEach(x -> {
                        final String fileName = x.getFileName().toString();
                        System.out.println("fileName = " + x.toFile().getAbsolutePath());
                        final String[] split = fileName.split(" ");
                        if (split.length > 1) {
                            final String key = split[0].toUpperCase();
                            kvalus.computeIfAbsent(key, k -> new ArrayList<>()).add(x.toString());
                            final int andIncrement = map.computeIfAbsent(key, k -> new AtomicInteger(0)).incrementAndGet();
                            if (andIncrement > 1) {
                                System.out.println(andIncrement + " " + x);
                                for (String s : kvalus.get(key)) {
                                    System.out.println("\t" + s);
                                }
                            }
                        }
                    });
        } catch (Exception e) {

        }
    }

    public static void main1(String[] args) {
        final HashMap<String, AtomicInteger> map = new HashMap<>();
        final HashMap<String, ArrayList<String>> kvalus = new HashMap<>();
        try {
            final List<String> collect = Files.readAllLines(Paths.get("f:\\data.txt")).stream().collect(Collectors.toList());
            for (String x : collect) {
                final String trim = x.trim();
                if (trim.length() != 0) {
                    final String[] split = trim.split(" ");
                    if (split.length > 1) {
                        final String key = split[0].toUpperCase();
                        kvalus.computeIfAbsent(key, k -> new ArrayList<>()).add(x);
                        final int andIncrement = map.computeIfAbsent(key, k -> new AtomicInteger(0)).incrementAndGet();
                        if (andIncrement > 1) {
                            System.out.println(andIncrement + " " + x);
                            for (String s : kvalus.get(key)) {
                                System.out.println("\t" + s);
                            }
                        }
                    }
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}
